package com.adityayadav.parallelism.core;

import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class ThreadPool {

	protected ArrayList<Thread> threads = new ArrayList<Thread>();
	
	protected BlockingQueue<ITask> taskQueue = new LinkedBlockingQueue<ITask>();
	
	public ThreadPool(int numberOfThreads) throws Exception {
		for (int i=0; i<numberOfThreads; i++){
			Thread cnpThread = new Thread(this);
			threads.add(cnpThread);
			cnpThread.start();
		}
	}
	
	public void setNumberOfThreads(int numberOfThreads){
		synchronized (this){
			if (numberOfThreads > threads.size()){
				for (int i=threads.size(); i<numberOfThreads; i++){
					Thread cnpThread = new Thread(this);
					threads.add(cnpThread);
					cnpThread.start();
				}	
			} else if (numberOfThreads < threads.size()){
				for (int i=numberOfThreads; i<threads.size(); i++){
					threads.get(numberOfThreads).setActive(false);
					threads.remove(numberOfThreads);
				}
			}
			// if same do nothing
		}
	}
	
	public int getNumberOfThreads(){
		return threads.size();
	}
	
	public boolean addTask(ITask task){
		return taskQueue.add(task);
	}
	
	public ITask takeTask() throws Exception {
		return taskQueue.take();
	}
	
	public void removeThread(Thread thread){
		synchronized (this){
			threads.remove(thread);
		}
	}
	
	public boolean isTaskQueueEmpty(){
		return taskQueue.isEmpty();
	}
	
	public boolean isIdle(boolean ignorePendingTasks){
		if (!ignorePendingTasks && !taskQueue.isEmpty()) return false;
		synchronized (this){
			for (Thread thread: threads){
				if (!thread.isIdle()) return false;
			}
		}
		return true;
	}
}
